#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <winsock2.h>
#include <string>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
class ClientHandler {
private:
    std::thread receiveThread;
    std::thread sendThread;
    std::mutex mtx;
    std::condition_variable cv;
    bool readyToSend;
    std::string messageToSend;
    bool stop;
    SOCKET clientSocket;
public:
    ClientHandler(SOCKET socket) : clientSocket(socket), stop(false) {}
    void start() {
        readyToSend = false;
        receiveThread = std::thread(&ClientHandler::receiveData, this);
        sendThread = std::thread(&ClientHandler::sendData, this);
        receiveThread.detach();
        sendThread.detach();
    }
    void stopHandler() {
        stop = true;
        cv.notify_all();
    }
    void sendMessage(const std::string& message) {
        std::unique_lock<std::mutex> lock(mtx);
        messageToSend = message;
        readyToSend = true;
        cv.notify_all();
    }
private:
    void receiveData() {
        while (!stop) {
            char buffer[1024];
            memset(buffer, 0, sizeof(buffer));
            int bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0);
            if (bytesRead > 0) {
                std::cout << "Received message from server: " << buffer << std::endl;
            }
        }
    }
    void sendData() {
        while (!stop) {
            std::unique_lock<std::mutex> lock(mtx);
            cv.wait(lock, [this] { return readyToSend || stop; });
            if (stop) {
                break;
            }
            const char* message = messageToSend.c_str();
            send(clientSocket, message, strlen(message), 0);
            std::cout << "Sending message to server: " << messageToSend << std::endl;
            readyToSend = false;
            cv.notify_all();
        }
    }
};
int main() {
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        std::cerr << "Failed to initialize Winsock" << std::endl;
        return 1;
    }
    SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (clientSocket == INVALID_SOCKET) {
        std::cerr << "Failed to create socket" << std::endl;
        WSACleanup();
        return 1;
    }
    sockaddr_in serverAddr; 
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8888);
    if (inet_pton(AF_INET, "10.133.83.20", &(serverAddr.sin_addr)) <= 0) {
        std::cerr << "Failed to convert server IP address" << std::endl;
        closesocket(clientSocket);
        WSACleanup();
        return 1;
    }
    if (connect(clientSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
        std::cerr << "Failed to connect to server" << std::endl;
        closesocket(clientSocket);
        WSACleanup();
        return 1;
    }
    ClientHandler client(clientSocket);
    client.start();
    std::string input;
    while (true) {
        std::getline(std::cin, input);
        if (input == "exit") {
            break;
        }
        client.sendMessage(input);
    }
    client.stopHandler();
    closesocket(clientSocket);
    WSACleanup();
    return 0;
}